{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Dictionaries and Sets" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" }, "tags": [ "remove-cell" ] }, "source": [ "**CS1302 Introduction to Computer Programming**\n", "___" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-11-27T11:20:04.656873Z", "start_time": "2020-11-27T11:20:04.651575Z" }, "slideshow": { "slide_type": "fragment" }, "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "import random\n", "import matplotlib.pyplot as plt\n", "%reload_ext mytutor" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Motivation for associative container" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The following code simulates the outcomes from rolling a dice multiple times." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:06.648131Z", "start_time": "2020-11-06T21:06:06.640645Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 3 3 5 1 5 5 6 6 3\n" ] } ], "source": [ "dice_rolls = [random.randint(1, 6) for i in range(10)]\n", "print(*dice_rolls)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**What is the distribution, i.e., fractional counts?**" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:06.960356Z", "start_time": "2020-11-06T21:06:06.727143Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "(0.0, 1.0)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "distribution = [dice_rolls.count(i) / len(dice_rolls) for i in range(7)]\n", "plt.stem(range(7), distribution)\n", "plt.xlabel(\"Outcomes\")\n", "plt.title(\"Distribution\")\n", "plt.ylim(0, 1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In the above code, `distribution[i]` stores the fractional count of outcome `i`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "However, `distribution[0]` is `0` because a dice does not have outcome `0`. Can we avoid such redundancy?" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:07.140502Z", "start_time": "2020-11-06T21:06:06.962531Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "(0.0, 1.0)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "distinct_outcomes = [\n", " outcome for outcome in range(1, 7) if dice_rolls.count(outcome) > 0\n", "]\n", "distribution = [\n", " dice_rolls.count(distinct_outcomes[i]) / len(dice_rolls)\n", " for i in range(len(distinct_outcomes))\n", "]\n", "\n", "plt.stem(distinct_outcomes, distribution)\n", "plt.xlabel(\"Outcomes\")\n", "plt.title(\"Distribution\")\n", "plt.ylim(0, 1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In the above code, \n", "- `distinct_outcomes` stores the list of distinct outcomes, and\n", "- `distribution[distinct_outcomes[i]]` stores the fractional count of the `i`-th distinct outcome." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "What about finding the distribution of characters in an article? \n", "There are 1,112,064 unicode characters. Can we:\n", "- Obtain the distribution efficiently without creating an entry for each unicode character?\n", "- Compute the set of distinct characters efficiently without iterating over the set of all unicode characters?\n", "- Access the fractional count of a particular character efficiently without searching through the list of distinct outcomes?\n", "- Index `distribution` directly by the distinct characters in the article?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "What we need is a composite data type that\n", "- can keep a set of *unique keys of different types* (such as the characters in our example), and\n", "- associate to different keys possibly different *values of any types* (such as the fractional counts of the characters).\n", "\n", "Such a data structure is called an [associative container](https://en.wikipedia.org/wiki/Associative_containers)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to use associative containers in Python?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "There are two built-in classes for associative containers:\n", "- `set` can store a set of unique keys of possibly different types.\n", "- `dict`ionary can store a set of key-value pairs." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We have already used sets and dictionaries before." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:07.407580Z", "start_time": "2020-11-06T21:06:07.402034Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 400\n", "a = (lambda **kwargs: kwargs)(start=0, stop=5, step=1)\n", "b = set([1, 1, 2, 3, 3, 3])\n", "assert len(a) == len(b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Both `set` and `dict` \n", "- implement `len` method that returns the number of keys, and\n", "- are mutable, so we can add/remove keys and values and modify their object references." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Constructing associative containers" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to create set/dictionary?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Similar to tuple/list, we can use enclosure, constructors, and comprehension." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to create a set/dict by enumerating its keys/values?**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For `dict`, enclose a comma-separated sequence of `key : value` pairs by braces `{` and `}`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:07.883687Z", "start_time": "2020-11-06T21:06:07.876803Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 350\n", "empty_dictionary = {}\n", "a = {\"a\": 0, \"b\": 1}\n", "b = {**a, \"c\": 0, \"d\": 1}" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "For `set`, omit `: value`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:07.983855Z", "start_time": "2020-11-06T21:06:07.976591Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "a = {(1, 2.0), print, *range(2), *\"23\"}\n", "empty_set = {*()} # Why not use {}?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "We can also create a set/dictionary from other objects using their constructors `set`/`dict`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.067481Z", "start_time": "2020-11-06T21:06:08.061044Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 550\n", "empty_set = set()\n", "string2set = set(\"abc\")\n", "range2set = set(range(2))\n", "list2set = set([\"abc\", range(2)])\n", "set2set = set(list2set)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.081891Z", "start_time": "2020-11-06T21:06:08.075946Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 650\n", "empty_dict = dict()\n", "enumerate2dict = dict(enumerate(\"abc\"))\n", "zip2dict = dict(zip(\"abc\", \"123\"))\n", "kwargs2dict = dict(one=1, two=2)\n", "dict2dict = dict(kwargs2dict)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** `dict` also has a [*class method* `fromkeys`](https://docs.python.org/3/library/stdtypes.html#dict.fromkeys) to construct a dictionary with keys from iterable pointing to a default value. Create a dictionary using `fromkeys` with keys being the non-negative integers smaller than `100` and values being `0`. \n", "\n", "*Hint:* Use `dict.fromkeys` since a class method is bound to the class rather than an object of the class." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.247405Z", "start_time": "2020-11-06T21:06:08.177552Z" }, "nbgrader": { "grade": false, "grade_id": "fromkeys", "locked": false, "schema_version": 3, "solution": true, "task": false } }, "outputs": [ { "data": { "text/plain": [ "\u001b[0;31mSignature:\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterable\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m/\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mDocstring:\u001b[0m Create a new dictionary with keys from iterable and values set to value.\n", "\u001b[0;31mType:\u001b[0m builtin_function_or_method\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "dict.fromkeys?\n", "### BEGIN SOLUTION\n", "fromkeys_dict = dict.fromkeys(range(100), 0)\n", "### END SOLUTION\n", "\n", "# test\n", "assert all(fromkeys_dict[k] == 0 for k in fromkeys_dict)" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-11-01T09:25:48.937507Z", "start_time": "2020-11-01T09:25:48.928030Z" }, "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to use a rule to construct a set/dictionary?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The following function uses a one-line dictionary comprehension to return the distribution of items in a sequence:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.402210Z", "start_time": "2020-11-06T21:06:08.396535Z" }, "tags": [] }, "outputs": [], "source": [ "def distribute(seq):\n", " return {k: seq.count(k) / len(seq) for k in set(seq)}" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAEWCAYAAAB2X2wCAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAV3klEQVR4nO3de5TkZX3n8fcnA0bAy0QZszKAoEGRrFFje5cTspoAXlbNZiOowZi4yCZq4i1ivKyr2ZUsG3fXFUKIYYm6R8walqAhjms8ioEoNAoMSHBnUWHA6CCCckl04Lt/1K+1pulLdddvpqufer/O6UP/LvWtbxXdn3nqqfo9napCkrT+/dhaNyBJ6oeBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANd60qSM5K8radaBye5PcmGbvszSV7RR+2u3l8neVlf9aTl7LXWDUjDknwN+ElgJ3A38GXgA8CZVXVPVZ20gjqvqKpPLXZOVV0P3G/cnrv7ewfwU1X10qH6x/ZRWxqVI3RNoudV1f2BhwGnAG8C/rTPO0jiYEbNMdA1sarqtqo6H3gR8LIk/zzJ2Ul+HyDJ/kk+nuTWJLck+VySH0vyQeBg4GPdlMrvJjkkSSX5jSTXA58e2jcc7o9IckmS25L8ZZIHdfd1VJLtw/0l+VqSZyU5Bvg94EXd/V3RHf/hFE7X11uTfD3Jt5J8IMkDu2NzfbwsyfVJbk7ylt377KpFBromXlVdAmwHjpx36PXd/k0Mpml+b3B6/SpwPYOR/v2q6j8N3ebngEcDRy9ydycAvw4cwGDa570j9PcJ4D8CH+nu77ELnPZr3dfPAw9nMNXzvnnnPAN4FPBM4O1JHr3cfUvDDHStFzcBD5q37wfAQ4GHVdUPqupztfziRO+oqjuq6q5Fjn+wqq6qqjuAtwG/Mvem6ZheArynqq6rqtuBNwPHzXt18O+r6q6qugK4AljoHwZpUQa61ovNwC3z9p0KbAM+meS6JCePUOeGFRz/OrA3sP/IXS7ugK7ecO29GLyymPMPQ9/fSU9v2Gp6GOiaeEmeyCDQ/3Z4f1V9r6peX1UPB54HvC7JM+cOL1JuuRH8QUPfH8zgVcDNwB3AvkM9bWAw1TNq3ZsYvMk7XHsn8M1lbieNzEDXxErygCTPBc4BPlRVW+cdf26Sn0oS4LsMPuZ4d3f4mwzmqlfqpUmOSLIv8E7go1V1N/AV4L5JnpNkb+CtwI8P3e6bwCFJFvud+jDw2iSHJrkfP5pz37mKHqUFGeiaRB9L8j0G0x9vAd4DvHyB8w4DPgXcDvwdcHpVfaY79m7grd0nYN6wgvv+IHA2g+mP+wKvgcEnboDfBN4P3MhgxD78qZf/1f3320m+uEDds7raFwJfBf4RePUK+pKWFf/AhSS1wRG6JDVi2UBPclZ3IcRVixxPkvcm2ZbkyiQ/23+bkqTljDJCPxs4ZonjxzKYyzwMOBH4o/HbkiSt1LKBXlUXcu/P/w57PvCBGvg8sDHJQ/tqUJI0mj4WKNrMrhdjbO/2fWP+iUlOZDCKZ7/99nvC4Ycf3sPdS9L0uOyyy26uqk0LHesj0LPAvgU/OlNVZwJnAszMzNTs7GwPdy9J0yPJ1xc71senXLaz69V1BzK4Kk6StAf1EejnAyd0n3Z5CnBbVd1rukWStHstO+WS5MPAUcD+3XrQ/47BgkVU1RnABcCzGSySdCcLX9EnSdrNlg30qjp+meMF/FZvHUmSVsUrRSWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEaMFOhJjklybZJtSU5e4PgDk3wsyRVJrk7y8v5blSQtZdlAT7IBOA04FjgCOD7JEfNO+y3gy1X1WOAo4A+T3KfnXiVJSxhlhP4kYFtVXVdV3wfOAZ4/75wC7p8kwP2AW4CdvXYqSVrSKIG+GbhhaHt7t2/Y+4BHAzcBW4Hfrqp75hdKcmKS2SSzO3bsWGXLkqSFjBLoWWBfzds+GrgcOAB4HPC+JA+4142qzqyqmaqa2bRp0wpblSQtZZRA3w4cNLR9IIOR+LCXA+fWwDbgq8Dh/bQoSRrFKIF+KXBYkkO7NzqPA86fd871wDMBkvwk8Cjguj4blSQtba/lTqiqnUleBWwBNgBnVdXVSU7qjp8BvAs4O8lWBlM0b6qqm3dj35KkeZYNdICqugC4YN6+M4a+vwn4xX5bkySthFeKSlIjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWrESIGe5Jgk1ybZluTkRc45KsnlSa5O8tl+25QkLWev5U5IsgE4DfgFYDtwaZLzq+rLQ+dsBE4Hjqmq65M8ZDf1K0laxCgj9CcB26rquqr6PnAO8Px557wYOLeqrgeoqm/126YkaTmjBPpm4Iah7e3dvmGPBH4iyWeSXJbkhIUKJTkxyWyS2R07dqyuY0nSgkYJ9Cywr+Zt7wU8AXgOcDTwtiSPvNeNqs6sqpmqmtm0adOKm5UkLW7ZOXQGI/KDhrYPBG5a4Jybq+oO4I4kFwKPBb7SS5eSpGWNMkK/FDgsyaFJ7gMcB5w/75y/BI5MsleSfYEnA9f026okaSnLjtCrameSVwFbgA3AWVV1dZKTuuNnVNU1ST4BXAncA7y/qq7anY1LknaVqvnT4XvGzMxMzc7Orsl9S9J6leSyqppZ6JhXikpSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0YKdCTHJPk2iTbkpy8xHlPTHJ3kl/ur0VJ0iiWDfQkG4DTgGOBI4DjkxyxyHl/AGzpu0lJ0vJGGaE/CdhWVddV1feBc4DnL3Deq4G/AL7VY3+SpBGNEuibgRuGtrd3+34oyWbghcAZSxVKcmKS2SSzO3bsWGmvkqQljBLoWWBfzdv+r8CbqurupQpV1ZlVNVNVM5s2bRqxRUnSKPYa4ZztwEFD2wcCN807ZwY4JwnA/sCzk+ysqvP6aFKStLxRAv1S4LAkhwI3AscBLx4+oaoOnfs+ydnAxw1zSdqzlg30qtqZ5FUMPr2yATirqq5OclJ3fMl5c0nSnjHKCJ2qugC4YN6+BYO8qn5t/LYkSSvllaKS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJaoSBLkmNMNAlqREGuiQ1wkCXpEYY6JLUCANdkhphoEtSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaYaBLUiMMdElqhIEuSY0w0CWpEQa6JDXCQJekRhjoktQIA12SGjFSoCc5Jsm1SbYlOXmB4y9JcmX3dXGSx/bfqiRpKcsGepINwGnAscARwPFJjph32leBn6uqnwHeBZzZd6OSpKWNMkJ/ErCtqq6rqu8D5wDPHz6hqi6uqu90m58HDuy3TUnSckYJ9M3ADUPb27t9i/kN4K8XOpDkxCSzSWZ37NgxepeSpGWNEuhZYF8teGLy8wwC/U0LHa+qM6tqpqpmNm3aNHqXkqRl7TXCOduBg4a2DwRumn9Skp8B3g8cW1Xf7qc9SdKoRhmhXwocluTQJPcBjgPOHz4hycHAucCvVtVX+m9TkrScZUfoVbUzyauALcAG4KyqujrJSd3xM4C3Aw8GTk8CsLOqZnZf25Kk+VK14HT4bjczM1Ozs7Nrct+StF4luWyxAbNXikpSIwx0SWqEgS5JjTDQJakRBrokNcJAl6RGGOiS1AgDXZIaMcpaLpIact6XbuTULddy0613ccDGfXjj0Y/iBY9fagHVPVNL4zPQpSly3pdu5M3nbuWuH9wNwI233sWbz90KsOIg7rOW+uGUizRFTt1y7Q8DeM5dP7ibU7dcu6a11A8DXZoiN91614r276la6oeBLk2RAzbus6L9e6qW+mGgS0PO+9KNPP2UT3PoyX/F00/5NOd96ca1bqlXbzz6Ueyz94Zd9u2z9wbeePSj1rSW+uGbolJnGt7km3scv/vRK/n+3feweYxPpvRZS/0w0KXOUm/ytRRSL3j8Zj58yfUAfOSVT52YWhqfUy5Sxzf5tN5N7QjdCyI03wEb9+HGBcLbN/nUl92dO1M5Qp+bK73x1rsofjRX2tobYFoZ3+TT7rQncmcqA90LIrSQFzx+M+/+pcdwnw2DX4vNG/fh3b/0GF+5qRd7InemcsrFuVItxjf5tLvsidyZykCf5LlS5/ZXbhqeMx/j+rcncmcqp1wmda7Uuf2Vm4bnzMfYhj2RO1MZ6JM6V+rc/spNw3PmY2zDnsidqZxygcmcK3Vuf+Wm4TnzMbZjd+fOVI7QJ5WLHa3cNDxnPkaNykCfILtjjq3PxaYmceGqSX0/pE8+xpVr/ed+MVM75TKJ+l7saBr+Os00LBDlY1yZafi5X4yBPmH6nGPrc7GpSV64ahLfD+mbj3F00/JzvxCnXBrmX6fRNJrmn/t1NUKf1AsPJrWvPi9k6PuiiEl9zvo0DY9xEk3yz/3utm5G6JN64cGk9gWT+9dpJvk568s0PMZJNak/93vCugn0Sb3wYFL7gn4vZOiz1iQ/Z32Zhsc4qSb1535PWDdTLpM6lzWpfc2ZxL9OM+nPWR+m4TFOskn8ud8T1s0IfVIvPJjUvibZNDxn0/AYNXlGCvQkxyS5Nsm2JCcvcDxJ3tsdvzLJz/bd6KTOZU1qX5NsGp6zaXiMmjzLTrkk2QCcBvwCsB24NMn5VfXlodOOBQ7rvp4M/FH3395M6sUVk9rXJJuG52waHqMmT6pq6ROSpwLvqKqju+03A1TVu4fO+WPgM1X14W77WuCoqvrGYnVnZmZqdnZ2xQ3/j+NfzT/bcQNHPPQBK77tfF/+xncBmq7Vdz1rWcta49f6h00H8fIP//dV3T7JZVU1s9CxUd4U3QzcMLS9nXuPvhc6ZzOwS6AnORE4sdu8vQv+1dgfuHmVt53GWn3Xs5a1rDVmrV8/532rrfWwxQ6MEuhZYN/8Yf0o51BVZwJnjnCfSzeUzC72L5S1dn89a1nLWpNTa9gob4puBw4a2j4QuGkV50iSdqNRAv1S4LAkhya5D3AccP68c84HTug+7fIU4Lal5s8lSf1bdsqlqnYmeRWwBdgAnFVVVyc5qTt+BnAB8GxgG3An8PLd1zLQw7TNlNXqu561rGWtyan1Q8t+ykWStD6smytFJUlLM9AlqRHrKtCTHJLkqrXuYyFJDk9ycZKtST6bZP+17mnSJPkvSX5naHtLkvcPbf9hktetsGbvPxNJLu6z3qRJsjHJb651HwtJ8pok1yT5n2vdy0KSvCPJG9a6j8Wsq0DfnbpP6Iz7fLy0qh4DXAyc1ENbrbkYeBpA91zvD/z00PGnARetQV+7qKqnrXUPu9lGYCIDnUFfz66ql6x1I+vRegz0vZL8WbcI2EeT7LvaQt3o7pokpwNfZNfP0q9IVf19VV3Xbd4X+MdV9rRfkr9KckWSq5K8aLU9dfVe19W5anh0vIo6c8/VnyS5Osknk6x06cCL6AKdQZBfBXwvyU8k+XHg0cCXVtHehjH72kWS28e5fVdjl1cOSd6Q5B1j1DsvyWXdYzxx+Vss6RTgEUkuT3LqmLV6k+QM4OHA+UleO2atE7qMuCLJB8es9ZZuccJPAWOtrpbkpUku6Z77P+7WyupPVa2bL+AQBlegPr3bPgt4w5j17gGe0mOPRwPXABtXeft/BfzJ0PYDx+jlCcBWYD/gfsDVwOPHeK52Ao/rtv+cwSuSldb5GnAw8EoGr2LexeAjr08HLlyrvubVvL2Hn4NDgKuGtt/AYE2k1dZ7UPfffRj8Q/jgvnqbpK/u52P/MWv8NHDtXJ25526VteZ+h/YFHsDgo9mryhwGA5aPAXt326cDJ/T5/K3HEfoNVTX3svxDwDPGrPf1qvr8mDWAH04j/CnwL6vq1lWW2Qo8K8kfJDmyqm4bo6VnAP+7qu6oqtuBc4Ejx6j31aq6vPv+MgbBsFJzo/SnAX/Xfc1tr3buuo++Jt1rklwBfJ7BK8nD1rifSfYvgI9W1c0AVXXLGLWOZPA7dGdVfZd7X1S5Es9k8A/EpUku77YfPka9e1k3f7FoyPwPzo/7Qfo7xrz9sAMYXCX7f1dboKq+kuQJDEat707yyap65yrLLbTGzjj+aej7uxmMFldqbh79MQxGmjcArwe+y+AV11r11bed7Dqled/VFkpyFPAs4KlVdWeSz4xTbwqE8XNhWF+1AvxZVb25p3r3sh5H6AdnsKQvwPHA365lM/N8h0E4rVqSA4A7q+pDwH8GxvljIRcCL0iyb5L9gBcCnxunvx5cBDwXuKWq7u5GTxuBpzIYrbfim8BDkjy4e3/guWPUeiDwnS7MDweeMmZv3wPuP2aNSfY3wK8keTBAkgeNUetC4IVJ9klyf+B5Y/b1y0keMtdXkkVXTlyN9Rjo1wAvS3Il8CAGf0xjUjwQeMWYNR4DXNK9JHsL8PurLVRVXwTOBi4BvgC8v6pW86Zjn7Yy+HTL5+ftu23uJXILquoHwDsZPO8fB/5+jHKfYPBhgCsZvOcw1hRhVX0buKh7o3xi3hTtS1VdDfwH4LPdNNV7xqj1ReAjwOXAXzDGgKgGfxTorcAnu/+X/wd46GrrLcRL/yWpEetxhC5JWoCBLkmNMNAlqREGuiQ1wkCXpEYY6Gre3Nos3foqL17rfqTdxUDXNDkEMNDVLANd0+QU4MhupbvXJtmQ5NQkl3Yr870SBpfad2va/3mSryQ5JclLulXytiZ5RHfev+4uzrkiyYVr+sgk1udaLtJqncxgpbznAnTL0N5WVU/sLs+/KMknu3Mfy2B1vFuA6xhcZfukJL8NvBr4HeDtwNFVdWOSjXv2oUj35ghd0+wXgRO6ZRa+ADyYH61ieGlVfaOq/gn4f8Bc0G/lR6s5XgScneTfAP2uay2tgiN0TbMAr66qLbvsHKxuOLyC4z1D2/fQ/d5U1UlJngw8B7g8yeO6dVKkNeEIXdNk/iqDW4B/m2RvgCSP7FalHEmSR1TVF6rq7cDNjPEXr6Q+OELXNLkS2NmtwHc28N8YTJ98MUmAHcALVlDv1CSHMRjp/w1wRZ/NSivlaouS1AinXCSpEQa6JDXCQJekRhjoktQIA12SGmGgS1IjDHRJasT/BzY9QzuEqq70AAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_distribution(seq):\n", " dist = distribute(seq)\n", " plt.stem(\n", " dist.keys(), # set-like view of the keys\n", " dist.values(), # view of the values\n", " )\n", " plt.xlabel(\"Items\")\n", " plt.title(\"Distribution\")\n", " plt.ylim(0, 1)\n", "\n", "\n", "plot_distribution(\"What is the distribution of different characters?\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- The object methods `keys` and `values` provide a dynamic [view](https://docs.python.org/3/glossary.html#term-dictionary-view) of the keys. \n", "- Unlike a copy, subsequent changes to the dictionary are also reflected in a previously returned view.\n", "- `items` provides a set-like view of the key-value pairs." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.644114Z", "start_time": "2020-11-06T21:06:08.639702Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 500\n", "a = dict(enumerate(\"abc\"))\n", "views = a.keys(), a.values(), a.items()\n", "print(a.pop(1)) # remove the key 1 and its associated value\n", "print(a.popitem()) # remove and return one key-value pair\n", "a.clear() # clear the dictionary" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "`set` has `pop` and `clear` but not `popitem`. However, `set.pop` behaves like `dict.popitem` instead of `dict.pop`." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.652435Z", "start_time": "2020-11-06T21:06:08.645934Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 250\n", "a = set(\"abc\")\n", "print(a.pop()) # remove and return an element\n", "a.clear() # clear the set" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Exercise** Use one-line comprehension to return a set of composite numbers smaller than `stop`. \n", "\n", "*Hint:* You do not need to worry about duplicate elements for `set`." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.756081Z", "start_time": "2020-11-06T21:06:08.737677Z" }, "nbgrader": { "grade": false, "grade_id": "set-comprehension", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4 6 8 9 10 12 14 15 16 18 20 21 22 24 25 26 27 28 30 32 33 34 35 36 38 39 40 42 44 45 46 48 49 50 51 52 54 55 56 57 58 60 62 63 64 65 66 68 69 70 72 74 75 76 77 78 80 81 82 84 85 86 87 88 90 91 92 93 94 95 96 98 99\n" ] } ], "source": [ "def composite_set(stop):\n", " ### BEGIN SOLUTION\n", " return {x for factor in range(2, stop) for x in range(factor * 2, stop, factor)}\n", " ### END SOLUTION\n", "\n", "\n", "print(*sorted(composite_set(100)))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Hashability" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "For `set` and `dict`, \n", "- identical keys are merged to the same entry even though\n", "- values associated with different keys can be the same." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:08.924986Z", "start_time": "2020-11-06T21:06:08.917894Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 350\n", "a = {0: \"a\", 0.0: \"b\", 2: \"b\"}\n", "b = {0j, 0, 0.0, \"\", False}\n", "assert 0 == 0.0 == 0j == False != \"\"" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "This is implemented efficiently by [*hashing*](https://docs.python.org/3/glossary.html#term-hashable). A key must be a hashable object which:\n", "\n", "- has a hash value (returned by `__hash__` method) that never changes during its lifetime, and\n", "- can be compared (using `__eq__` method) to other objects. \n", " *Hashable objects which compare equal must have the same hash value.*" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:09.025314Z", "start_time": "2020-11-06T21:06:09.014575Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " may be hashable. E.g., hash(0) == 0\n", " may be hashable. E.g., hash(0.0) == 0\n", " may be hashable. E.g., hash(0j) == 0\n", " may be hashable. E.g., hash('') == 0\n", " may be hashable. E.g., hash(False) == 0\n", " may be hashable. E.g., hash(()) == 5740354900026072187\n", " may not be hashable.\n", " may not be hashable.\n", " may not be hashable.\n", " may be hashable. E.g., hash(frozenset()) == 133146708735736\n", " may not be hashable.\n" ] } ], "source": [ "def hashable(obj):\n", " try:\n", " hash(obj)\n", " except Exception:\n", " return False\n", " return True\n", "\n", "\n", "for i in 0, 0.0, 0j, \"\", False, (), [], {}, set(), frozenset(), ([],):\n", " if hashable(i):\n", " print(\"{} may be hashable. E.g., hash({!r}) == {}\".format(type(i), i, hash(i)))\n", " else:\n", " print(\"{} may not be hashable.\".format(type(i)))" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-11-01T08:18:58.573375Z", "start_time": "2020-11-01T08:18:58.567390Z" }, "slideshow": { "slide_type": "subslide" } }, "source": [ "**Why the key should be hashable?** \n", "**What is the use of a hash value?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Associative containers are implemented as *hash tables* for efficient lookup of key values." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:09.199204Z", "start_time": "2020-11-06T21:06:09.192584Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%html\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Most mutable objects are not hashable. Why? \n", " Mutating a key makes it a different key, which is [hard to track](https://hynek.me/articles/hashes-and-equality/)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "`set` has an immutable counterpart called `frozenset`, but `dict` does not have any immutable counterpart. Why? \n", "While elements of a set must be hashable and therefore mostly immutable, dictionary values may be of mutable types." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Python also uses dictionary for its global/local frames. \n", "Indeed, [hash collisions can slow down the lookup process](https://stackoverflow.com/questions/8271139/why-is-early-return-slower-than-else)." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Why equal objects must have the same hash but different objects may have the same hash? An example is given below:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:09.545081Z", "start_time": "2020-11-06T21:06:09.539538Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "assert hash(0) == hash(0.0) == hash(0j) == hash(False) == hash(\"\") and False != \"\"" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "hash-collision", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "1. To avoid duplicate keys occupying different entries in a hash table.\n", "2. Hash collision can be detected by `==` and handled by [collision resolution](https://en.wikipedia.org/wiki/Hash_table#Collision_resolution) techniques. To keep the hash table small, hash collision is unavoidable." ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "**Exercise** Should an immutable object always be hashable?" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "immutable_vs_hashable", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false } }, "source": [ "No. `hashable(([],))` returns False in particular because the value of an immutable object can still be changed if it points to a mutable object." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Exercise** Can we use the `id` of an object as its hash value?" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "id_vs_hash", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false } }, "source": [ "No because `id` remains unchanged even if the value of an object changes." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Accessing keys/values" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to traverse a set/dictionary?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Set and dictionaries are iterable. \n", "The for loop iterates over the keys." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:09.946276Z", "start_time": "2020-11-06T21:06:09.875228Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "c b d e a\n", "(0, 'a') (1, 'b') (2, 'c') (3, 'd') (4, 'e')\n" ] }, { "ename": "TypeError", "evalue": "'set' object is not subscriptable", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_374/939558128.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0melement\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0melement\u001b[0m \u001b[0;32min\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# TypeError\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: 'set' object is not subscriptable" ] } ], "source": [ "a = set(\"abcde\")\n", "b = dict(enumerate(\"abcde\"))\n", "print(*(element for element in a))\n", "print(*((key, b[key]) for key in b))\n", "a[0] # TypeError" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- For the dictionary `b`, we used subscription `b[key]` to access the value associated with `key`.\n", "- Unlike dictionary, set does not implement [`__getitem__`](https://docs.python.org/3/reference/datamodel.html#object.__getitem__) and is therefore not subscriptable." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Unlike tuple/list, `b[-1]` does not refer to the value of the last entry. (Dictionary is not ordered.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.056062Z", "start_time": "2020-11-06T21:06:10.048909Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "b[-1] # KeyError" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The above raises a key error because `-1` is not a key in the dictionary `b`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Dictionary implements the [`__setitem__`](https://docs.python.org/3/reference/simple_stmts.html#assignment-statements) method so we can enter a key value pair to a dictionary using the assignment operator." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.212433Z", "start_time": "2020-11-06T21:06:10.205926Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "'f'" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b[-1] = \"f\"\n", "b[-1]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To delete a key, we can use the function `del`." ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.301358Z", "start_time": "2020-11-06T21:06:10.292451Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "ename": "KeyError", "evalue": "-1", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_374/2302511900.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mb\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mKeyError\u001b[0m: -1" ] } ], "source": [ "del b[-1]\n", "b[-1]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "To avoid key error, we can check if a key is in a dictionary efficiently (due to hashing) using the `in` operator. \n", "The following is a different implementation of `distribute`." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.652024Z", "start_time": "2020-11-06T21:06:10.405798Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def distribute(seq):\n", " dist = {}\n", " for i in seq:\n", " dist[i] = (dist[i] if i in dist else 0) + 1 / len(seq)\n", " return dist\n", "\n", "\n", "plot_distribution(\"What is the distribution of different characters?\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Unlike the previous implementation using one-line dictionary comprehension, the above alternative implementation uses multiple lines of code to build the dictionary incrementally starting from an empty dictionary.\n", "```Python\n", "def distribute(seq):\n", " return {k : seq.count(k)/len(seq) for k in set(seq)}\n", "```\n", "Explain whether the alternative is more efficient." ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "efficient-distribution", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "It is more efficient because \n", "- the alternative implementation traverses `seq` once with near constant time lookup of the key, but\n", "- the list comprehension can traverse `seq` a multiple times linear in `len(seq)`, since every call to `seq.count` has to traverse `seq` once.\n", "\n", "Shorter code needs not be more efficient." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** `dict` also has a getter method `get` that conveniently returns a default value if the key does not exist. Rewrite the alternative implementation of `distribute` to use `get` instead of `in`." ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.867186Z", "start_time": "2020-11-06T21:06:10.654346Z" }, "nbgrader": { "grade": false, "grade_id": "get", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "\u001b[0;31mSignature:\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m/\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mDocstring:\u001b[0m Return the value for key if key is in the dictionary, else default.\n", "\u001b[0;31mType:\u001b[0m method_descriptor\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "dict.get?\n", "def distribute(seq):\n", " dist = {}\n", " for i in seq:\n", " ### BEGIN SOLUTION\n", " dist[i] = dist.get(i, 0) + 1 / len(seq)\n", " ### END SOLUTION\n", " return dist\n", "\n", "\n", "plot_distribution(\"What is the distribution of different characters?\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to traverse in ascending order of the keys?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We can apply the function `sorted` to a set/dictionary to return a sorted list of the keys." ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.872969Z", "start_time": "2020-11-06T21:06:10.869064Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 600\n", "a = set(reversed(\"abcde\"))\n", "b = dict(reversed([*enumerate(\"abcde\")]))\n", "sorted_elements = sorted(a)\n", "sorted_keys = sorted(b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Re-implement `plot_distribution` to plot the distribution in ascending order of the keys.\n", "\n", "*Hint:* Use the optional argument `key` of the function `sorted`." ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.890243Z", "start_time": "2020-11-06T21:06:10.874962Z" }, "nbgrader": { "grade": false, "grade_id": "sorted-keys", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_distribution(seq):\n", " dist = distribute(seq)\n", " # plt.stem(dist.keys(), dist.values())\n", " ### BEGIN SOLUTION\n", " dist_list = sorted(dist.items(), key=lambda p: p[0])\n", " plt.stem(\n", " [p[0] for p in dist_list], [p[1] for p in dist_list]\n", " )\n", " ### END SOLUTION\n", " plt.xlabel(\"Items\")\n", " plt.title(\"Distribution\")\n", " plt.ylim(0, 1)\n", "\n", "\n", "plot_distribution(\"What is the distribution of different characters?\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to add an element to a set and remove an element from it?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Instead of subscription, `set` has the `add`/`discard`/`remove` methods for adding/removing elements." ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:10.999497Z", "start_time": "2020-11-06T21:06:10.994027Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 400\n", "a = set(\"abc\")\n", "a.add(\"d\")\n", "a.discard(\"a\")\n", "a.remove(\"b\")\n", "a.clear()\n", "a.discard(\"a\") # no error\n", "a.remove(\"b\") # KeyError" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Other operators and methods" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Unlike `str`/`tuple`/`list`, `set` and `dict` do not implement addition `+` and multiplication `*`:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:11.147475Z", "start_time": "2020-11-06T21:06:11.141560Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "any(\n", " hasattr(container, attr)\n", " for attr in (\"__add__\", \"__mult__\")\n", " for container in (dict, set, frozenset)\n", ")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Use the unpacking operators `*` and `**` to concatenate two sets/dictionaries below into a new set/dictionary." ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:11.236075Z", "start_time": "2020-11-06T21:06:11.230787Z" }, "nbgrader": { "grade": false, "grade_id": "concatenate-sets", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "{'a', 'b', 'c', 'd', 'e'}" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "set1 = set(\"abc\")\n", "set2 = set(\"cde\")\n", "### BEGIN SOLUTION\n", "concatenated_set = {*set1, *set2}\n", "### END SOLUTION\n", "concatenated_set" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:11.244872Z", "start_time": "2020-11-06T21:06:11.238068Z" }, "nbgrader": { "grade": false, "grade_id": "concatenate-dictionaries", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/plain": [ "{0: 'a', 1: 'b', 2: 'd', 3: 'e', 4: 'f'}" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict1 = dict(enumerate(\"abc\"))\n", "dict2 = dict(enumerate(\"def\", start=2))\n", "### BEGIN SOLUTION\n", "concatenated_dict = {**dict1, **dict2}\n", "### END SOLUTION\n", "concatenated_dict" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "`set` overloads many other operators:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "ExecuteTime": { "end_time": "2020-11-18T03:07:40.764590Z", "start_time": "2020-11-18T03:07:40.753558Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 550\n", "a, b = {1, 2}, {2, 3}\n", "\n", "union = a | b\n", "assert all(i in union for i in a) and all(i in union for i in b)\n", "\n", "intersection = a & b\n", "assert all(i in a and i in b for i in intersection)\n", "\n", "assert intersection <= a <= union # subset\n", "assert union > b > intersection # proper superset\n", "assert len(a) + len(b) == len(intersection) + len(union)\n", "\n", "symmetric_difference = a ^ b\n", "assert all((i in a or i in b) and not (i in a and i in b) for i in symmetric_difference)\n", "assert symmetric_difference == union - intersection\n", "assert set.isdisjoint(intersection, symmetric_difference)\n", "assert len(union) == len(intersection) + len(symmetric_difference)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The following uses `&` and `-` to compare the sets of public attributes for `set` and `dict`:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:11.422313Z", "start_time": "2020-11-06T21:06:11.413114Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Common attributes: copy, clear, pop, update\n", "dict-specific attributes: popitem, values, fromkeys, setdefault, keys, items, get\n", "set-specific attributes: intersection, difference_update, add, symmetric_difference, difference, isdisjoint, issuperset, discard, symmetric_difference_update, intersection_update, union, issubset, remove\n" ] } ], "source": [ "set_attributes = {attr for attr in dir(set) if attr[0] != \"_\"}\n", "dict_attributes = {attr for attr in dir(dict) if attr[0] != \"_\"}\n", "print(\"Common attributes:\", \", \".join(set_attributes & dict_attributes))\n", "print(\"dict-specific attributes:\", \", \".join(dict_attributes - set_attributes))\n", "print(\"set-specific attributes:\", \", \".join(set_attributes - dict_attributes))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "For `set`, the intersection operation `&` can also be performed by\n", "- the class method `intersection` which returns the intersection of its arguments, and\n", "- the object method `intersection_update` which mutates a set object by intersecting the set with the arguments." ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:11.515024Z", "start_time": "2020-11-06T21:06:11.507575Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "a = {0, 1, 2}\n", "b = {1, 2, 3}\n", "c = set.intersection(a, b, {2, 3, 4})\n", "a.intersection_update(b, c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- All other set-specific methods have an associated operator except `isdisjoint` as shown below.\n", "- The object method for `union` is `update` not `union_update`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "| class method | object method | operator |\n", "| ---------------------- | ----------------------------- | ------------ |\n", "| `union` | `update` | `\\| ` |\n", "| `intersection` | `intersection_update` | `&` |\n", "| `symmetric_difference` | `symmetric_difference_update` | `^` |\n", "| `issubset` | | `<=` |\n", "| `issuperset` | | `>=` |\n", "| `isdisjoint` | | |" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "`dict` also has an `update` method that can update a dictionary using dictionary, iterables and keyword arguments:" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "ExecuteTime": { "end_time": "2020-11-18T03:13:27.594519Z", "start_time": "2020-11-18T03:13:27.586927Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "a = {}\n", "a.update(enumerate(\"a\"), b=2)\n", "b = a.copy()\n", "a.update(b, c=3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** For `dict`, there is also a method called [`setdefault`](https://stackoverflow.com/questions/3483520/use-cases-for-the-setdefault-dict-method). Use it to define a function `group_by_type` that \n", "- takes a sequence `seq` of objects and \n", "- returns a dictionary `d` such that `d[repr(t)]` returns the list of objects in `seq` of type `t`\n", "\n", "If there is no objects of type `t`, raise a key error." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2020-11-06T21:06:11.889952Z", "start_time": "2020-11-06T21:06:11.876280Z" }, "nbgrader": { "grade": false, "grade_id": "setdefault", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [], "source": [ "def group_by_type(seq):\n", " group = {}\n", " for i in seq:\n", " ### BEGIN SOLUTION\n", " group.setdefault(repr(type(i)), []).append(i)\n", " ### END SOLUTION\n", " return group\n", "\n", "\n", "group_by_type(\n", " [\n", " *range(3),\n", " *\"abc\",\n", " *[i / 2 for i in range(3)],\n", " *[(i,) for i in range(3)],\n", " *[[i] for i in range(3)],\n", " *[{i} for i in range(3)],\n", " *[{i: i} for i in range(3)],\n", " print,\n", " hash,\n", " int,\n", " str,\n", " float,\n", " set,\n", " dict,\n", " (i for i in range(10)),\n", " enumerate(\"abc\"),\n", " range(3),\n", " zip(),\n", " set.add,\n", " dict.copy,\n", " ]\n", ")" ] } ], "metadata": { "celltoolbar": "Create Assignment", "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.12" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "rise": { "enable_chalkboard": true, "scroll": true, "theme": "white" }, "toc": { "base_numbering": 1, "nav_menu": { "height": "195px", "width": "330px" }, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "454.418px", "left": "1533px", "top": "110.284px", "width": "261px" }, "toc_section_display": true, "toc_window_display": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }